package com.atbun.aclservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atbun.aclservice.entity.AclPermission;
import com.atbun.aclservice.entity.AclRolePermission;
import com.atbun.aclservice.entity.AclUser;
import com.atbun.aclservice.helper.MemuHelper;
import com.atbun.aclservice.helper.PermissionHelper;
import com.atbun.aclservice.mapper.PermissionMapper;
import com.atbun.aclservice.service.PermissionService;
import com.atbun.aclservice.service.RolePermissionService;
import com.atbun.aclservice.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.Permission;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2020-05-23
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, AclPermission> implements PermissionService {

    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private UserService userService;

    /**
     * 获取全部菜单
     * @return
     */
    @Override
    public List<AclPermission> indexAllPermission() {
        QueryWrapper<AclPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");
        List<AclPermission> permissionList = this.baseMapper.selectList(queryWrapper);

//        根据权限数据构建菜单数据
        List<AclPermission> result = PermissionHelper.bulid(permissionList);

        return result;
    }

    /**
     * 递归删除菜单
     * 思路：获取子节点菜单id放到list中
     *      使用删除list集合
     * @param id
     */
    @Override
    public void deletePermission(String id) {
//        1、把所有的id都封装到idList集合中
        List<String> idList = new ArrayList<>();
//        2、向idList中封装子节点的id
        this.selectPermissionChildById(id,idList);
//        3、向idList封装当前id
        idList.add(id);
//        4、执行删除
        baseMapper.deleteBatchIds(idList);
    }


    private void selectPermissionChildById(String id, List<String> idList) {
//     获取所有该id下的子节点id
        QueryWrapper<AclPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid",id);
        queryWrapper.select("id");
//        查找子菜单
        List<AclPermission> childList = baseMapper.selectList(queryWrapper);

//        遍历childList节点id存放到idList集合中(如下写法相当于循环,item相当于增强for循环的对象)
        childList.stream().forEach(item -> {
            idList.add(item.getId());
//            递归存放下一个id
            this.selectPermissionChildById(item.getId(),idList);
        });
    }

    /**
     * 给角色分配权限
     * 思路：角色与权限关系，一对多
     *      把角色id与权限id关系存入表中
     * @param roleId
     * @param permissionId
     */
    @Override
    public void saveRolePermissionRealtionShip(String roleId, String[] permissionId) {
//        先根据角色id删除角色与权限表的关系，因为要新建关系
        this.rolePermissionService.remove(new QueryWrapper<AclRolePermission>().eq("role_id",roleId));

//       使用集合把所有关系存起来，然后在一次性存入数据库
        List<AclRolePermission> aclRolePermissions = new ArrayList<>();
//        遍历菜单的所有id，然后往对象中设置值，再往集合中添加
        for (int i=0;i<permissionId.length;i++){
            AclRolePermission aclRolePermission =new AclRolePermission();
            aclRolePermission.setRoleId(roleId);
            aclRolePermission.setPermissionId(permissionId[i]);
            aclRolePermissions.add(aclRolePermission);
        }
//        添加到角色菜单表中
        rolePermissionService.saveBatch(aclRolePermissions);
    }

    /**
     * 通过角色id获取菜单信息
     * 思路：通过角色id查找角色菜单表acl_role_permission，得到所有的菜单id（一对多），
     *      查找菜单表全部数据，
     *      拿到菜单id去菜单表acl_permission查找菜单数据。
     *      菜单数据有层级关系，所以需要使用之前的递归build()
     *      最终目的：得到所有菜单，哪些是当前角色下面的菜单，用选中状态表示
     * @param roleId
     * @return
     */
    @Override
    public List<AclPermission> selectAllMenu(String roleId) {

//        根据角色id查找角色与菜单表,即得到了该角色的所有菜单id
        List<AclRolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<AclRolePermission>().eq("role_id", roleId));

//        查找菜单所有数据
        List<AclPermission> aclPermissionList = baseMapper.selectList(new QueryWrapper<AclPermission>().orderByAsc("id"));

//        遍历菜单集合，判断每一条菜单与当前角色id查找到的菜单id是否相同，如果相同，就设置一个标志，表示该菜单是当前角色的菜单
        for (int i=0; i<aclPermissionList.size();i++){
            AclPermission aclPermission = aclPermissionList.get(i);
            for (int k = 0;k<rolePermissionList.size();k++){
                AclRolePermission rolePermission = rolePermissionList.get(k);
                if (rolePermission.getPermissionId().equals(aclPermission.getId())){
                    aclPermission.setSelect(true); //返回前端时需要的选中状态
                }
            }
        }
//        遍历所有菜单，组成父子节点形式的数据格式返回
        List<AclPermission> permissionList = PermissionHelper.bulid(aclPermissionList);
        return permissionList;
    }

    /**
     * 根据用户id查询权限
     * @param userId
     * @return
     */
    @Override
    public List<String> selectPermissionValueByUserId(String userId) {
        List<String> selectPermissionValueList = null;
//        判断该用户是否是超级管理员
        if (this.isSysAdmin(userId)){
//            获取所有权限
            selectPermissionValueList = this.baseMapper.selectAllPermissionValue();
        }else{
//            根据用户id查询菜单
            selectPermissionValueList = baseMapper.selectPermissionValueByUserId(userId);
        }
        return selectPermissionValueList;
    }

    /**
     * 根据用户id获取菜单
     * @param userId
     * @return
     */
    @Override
    public List<JSONObject> selectPermissionByUserId(String userId) {
        List<AclPermission> selectPermissionList = null;
        if (this.isSysAdmin(userId)){
//            如果是超级管理员，获取所有菜单
            selectPermissionList = this.baseMapper.selectList(null);
        }else{
            selectPermissionList = this.baseMapper.selectPermissionByUserId(userId);
        }
        List<AclPermission> permissionList = PermissionHelper.bulid(selectPermissionList);

        List<JSONObject> result = MemuHelper.bulid(permissionList);
        return result;
    }


    /**
     * 判断是否是超级管理员
     * @param userId
     * @return
     */
    public boolean isSysAdmin(String userId){
        AclUser aclUser = userService.getById(userId);
        if (null != aclUser && "admin".equals(aclUser.getUsername())){
            return true;
        }
        return false;
    }




}
